home *** CD-ROM | disk | FTP | other *** search
- /*
- * tunnel driver test program.
- *
- * This program does ICMP echo reply. Can be used to measure
- * overhead of tunnel driver and associated process.
- */
- #include <machine/endian.h>
- #include <sys/types.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #include <sys/socket.h>
- #include <net/route.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <net/if.h>
- #if defined(__NetBSD__) || _BSDI_VERSION >= 199312
- #include <sys/select.h>
- #endif
- #include <net/if_tun.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <netinet/ip_icmp.h>
- #include <signal.h>
-
- int tun;
- struct ifaliasreq ifra;
-
- static void
- IcmpEcho(ptr, nb)
- u_char *ptr;
- int nb;
- {
- struct ip *pip;
- struct icmp *picmp;
- struct in_addr w;
-
- /* Validate IP header */
- pip = (struct ip *)ptr;
- if (pip->ip_v != IPVERSION)
- return;
- if (pip->ip_p != IPPROTO_ICMP)
- return;
- /* Validate ICMP header */
- picmp = (struct icmp *)(ptr + (pip->ip_hl << 2));
- if (picmp->icmp_type != ICMP_ECHO)
- return;
- /* Build reply packet */
- picmp->icmp_type = ICMP_ECHOREPLY;
- picmp->icmp_cksum += 8;
- w = pip->ip_src;
- pip->ip_src = pip->ip_dst;
- pip->ip_dst = w;
- write(tun, ptr, nb);
- }
-
- void
- gotinter()
- {
- int s;
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
-
- bzero(&ifra.ifra_addr, sizeof(ifra.ifra_addr));
- bzero(&ifra.ifra_broadaddr, sizeof(ifra.ifra_addr));
- bzero(&ifra.ifra_mask, sizeof(ifra.ifra_addr));
- ioctl(s, SIOCDIFADDR, &ifra);
-
- close(tun);
- exit(0);
- }
-
- struct tuninfo tuninfo;
-
- main()
- {
- int s;
- int one = 1;
- int val, nb;
- struct ifreq ifrq;
- char ifname[IFNAMSIZ];
- struct sockaddr_in *sin;
- char iobuff[500];
- fd_set rfds;
-
- tun = open("/dev/tun0", O_RDWR);
- if (tun < 0) {
- perror("open");
- exit(1);
- }
-
- /*
- * At first, name the interface.
- */
- strcpy(ifname, "tun0");
-
- bzero((char *)&ifra, sizeof(ifra));
- bzero((char *)&ifrq, sizeof(ifrq));
-
- strncpy(ifrq.ifr_name, ifname, IFNAMSIZ);
- strncpy(ifra.ifra_name, ifname, IFNAMSIZ);
- /*
- * Set interface address
- */
- sin = (struct sockaddr_in *)&(ifra.ifra_addr);
- sin->sin_family = AF_INET;
- val = inet_addr("100.123.111.2");
- sin->sin_addr.s_addr = val;
- sin->sin_len = sizeof(*sin);
- /*
- * Set destination address
- */
- sin = (struct sockaddr_in *)&(ifra.ifra_broadaddr);
- sin->sin_family = AF_INET;
- val = inet_addr("100.123.111.8");
- sin->sin_addr.s_addr = val;
- sin->sin_len = sizeof(*sin);
- /*
- */
- sin = (struct sockaddr_in *)&(ifra.ifra_mask);
- sin->sin_family = AF_INET;
- val = inet_addr("255.255.255.255");
- sin->sin_addr.s_addr = val;
- sin->sin_len = sizeof(*sin);
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- perror("socket");
- exit(1);
- }
-
- if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
- perror("SIOCAIFADDR");
- exit(1);
- }
-
- /*
- * Now, bring up the interface.
- */
- if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
- perror("SIOCGIFFLAGS");
- exit(1);
- }
-
- ifrq.ifr_flags |= IFF_UP;
- if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
- perror("SIOCSIFFLAGS");
- exit(1);
- }
- close(s);
-
- printf("Interface is now up!! (%d)\n", tun);
- signal(SIGINT, gotinter);
- val = ioctl(tun, TUNGIFINFO, &tuninfo);
- printf("val = %d\n", val);
- printf("TYPE = %d, MTU = %d\n", tuninfo.if_type, tuninfo.if_mtu);
-
- for (;;) {
- FD_ZERO(&rfds);
- FD_SET(0, &rfds); FD_SET(tun, &rfds);
- if (select(tun + 2, &rfds, NULL, NULL, NULL) < 0)
- break;
- if (FD_ISSET(tun, &rfds)) {
- nb = read(tun, iobuff, sizeof(iobuff));
- IcmpEcho(iobuff, nb);
- }
- if (FD_ISSET(0, &rfds)) {
- read(0, iobuff, sizeof(iobuff));
- break;
- }
- }
- }
-